/*
 *  Node.js Buffer.prototype.write()
 */

/*@include util-buffer.js@*/

/*---
{
    "custom": true
}
---*/

/* Custom because there are some differences to Node.js behavior. */

/*===
16 ABCDEFGHIJKLMNOP 4142434445464748494a4b4c4d4e4f50
3
3
16 fooDEbarIJKLMNOP 666f6f4445626172494a4b4c4d4e4f50
6
16 fooDEbarIJfoobar 666f6f4445626172494a666f6f626172
3
16 fooDEbarIJFOObar 666f6f4445626172494a464f4f626172
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
undefined undefined TypeError
object null TypeError
boolean true TypeError
boolean false TypeError
number 123 TypeError
object ABCDEFGH TypeError
undefined undefined 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
undefined null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
undefined true 1
16 fAAAAAAAAAAAAAAA 66414141414141414141414141414141
undefined false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
undefined -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
undefined 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
undefined 12 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
undefined 14 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
undefined [object Object] 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
null undefined 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
null null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
null true 1
16 fAAAAAAAAAAAAAAA 66414141414141414141414141414141
null false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
null -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
null 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
null 12 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
null 14 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
null [object Object] 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
true undefined 3
16 AfooAAAAAAAAAAAA 41666f6f414141414141414141414141
true null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
true true 1
16 AfAAAAAAAAAAAAAA 41664141414141414141414141414141
true false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
true -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
true 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
true 12 3
16 AfooAAAAAAAAAAAA 41666f6f414141414141414141414141
true 14 3
16 AfooAAAAAAAAAAAA 41666f6f414141414141414141414141
true [object Object] 3
16 AfooAAAAAAAAAAAA 41666f6f414141414141414141414141
false undefined 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
false null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
false true 1
16 fAAAAAAAAAAAAAAA 66414141414141414141414141414141
false false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
false -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
false 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
false 12 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
false 14 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
false [object Object] 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
-1 undefined RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 null RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 true RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 false RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 0 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 12 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 14 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
-1 [object Object] RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
0 undefined 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
0 null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
0 true 1
16 fAAAAAAAAAAAAAAA 66414141414141414141414141414141
0 false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
0 -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
0 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
0 12 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
0 14 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
0 [object Object] 3
16 fooAAAAAAAAAAAAA 666f6f41414141414141414141414141
12 undefined 3
16 AAAAAAAAAAAAfooA 414141414141414141414141666f6f41
12 null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
12 true 1
16 AAAAAAAAAAAAfAAA 41414141414141414141414166414141
12 false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
12 -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
12 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
12 12 3
16 AAAAAAAAAAAAfooA 414141414141414141414141666f6f41
12 14 3
16 AAAAAAAAAAAAfooA 414141414141414141414141666f6f41
12 [object Object] 3
16 AAAAAAAAAAAAfooA 414141414141414141414141666f6f41
14 undefined 2
16 AAAAAAAAAAAAAAfo 4141414141414141414141414141666f
14 null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
14 true 1
16 AAAAAAAAAAAAAAfA 41414141414141414141414141416641
14 false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
14 -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
14 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
14 12 2
16 AAAAAAAAAAAAAAfo 4141414141414141414141414141666f
14 14 2
16 AAAAAAAAAAAAAAfo 4141414141414141414141414141666f
14 [object Object] 2
16 AAAAAAAAAAAAAAfo 4141414141414141414141414141666f
[object Object] undefined 3
16 AAAAfooAAAAAAAAA 41414141666f6f414141414141414141
[object Object] null 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
[object Object] true 1
16 AAAAfAAAAAAAAAAA 41414141664141414141414141414141
[object Object] false 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
[object Object] -1 RangeError
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
[object Object] 0 0
16 AAAAAAAAAAAAAAAA 41414141414141414141414141414141
[object Object] 12 3
16 AAAAfooAAAAAAAAA 41414141666f6f414141414141414141
[object Object] 14 3
16 AAAAfooAAAAAAAAA 41414141666f6f414141414141414141
[object Object] [object Object] 3
16 AAAAfooAAAAAAAAA 41414141666f6f414141414141414141
===*/

function nodejsBufferWriteTest() {
    var b = Buffer('ABCDEFGHIJKLMNOP');
    print(b.length, String(b), printableNodejsBuffer(b));

    // Unlike typed write methods like writeUInt32BE(), returns
    // #bytes written (instead of offset + #bytes written)

    print(b.write('foo'));
    print(b.write('bar', 5));
    print(b.length, String(b), printableNodejsBuffer(b));

    // If string is longer than available size, it gets clamped.

    print(b.write('foobarquuxbaz', 10));
    print(b.length, String(b), printableNodejsBuffer(b));

    // Length argument can also be over buffer length and is
    // silently clamped.

    print(b.write('FOO', 10, 100));
    print(b.length, String(b), printableNodejsBuffer(b));

    // Offset argument over buffer length is rejected.
    // Negative offset and length are rejected.

    try {
        // offset exactly at end is ok
        b.fill(0x41);
        b.write('FOO', 16);
    } catch (e) {
        print(e.name);
    }
    print(b.length, String(b), printableNodejsBuffer(b));

    try {
        b.fill(0x41);
        b.write('FOO', -1);
    } catch (e) {
        print(e.name);
    }
    print(b.length, String(b), printableNodejsBuffer(b));

    try {
        b.fill(0x41);
        b.write('FOO', -1);
    } catch (e) {
        print(e.name);
    }
    print(b.length, String(b), printableNodejsBuffer(b));

    try {
        b.fill(0x41);
        b.write('FOO', 3, -1);
    } catch (e) {
        print(e.name);
    }
    print(b.length, String(b), printableNodejsBuffer(b));

    // Non-string values are not accepted - not even Buffers.

    [ undefined, null, true, false, 123,
      new Buffer('ABCDEFGH') ].forEach(function (arg) {
        try {
            b.fill(0x41);
            b.write(arg, 0);
        } catch (e) {
            print(typeof arg, String(arg), e.name);
        }
    });

    // Offset and length are integer coerced.

    var vals = [
        undefined, null, true, false, -1, 0, 12, 14,
        { valueOf: function () { return 4; } }
    ];

    vals.forEach(function (offset) {
        vals.forEach(function (length) {
            try {
                b.fill(0x41);
                print(offset, length, b.write('foo', offset, length));
            } catch (e) {
                print(offset, length, e.name);
            }
            print(b.length, String(b), printableNodejsBuffer(b));
        });
    });
}

try {
    nodejsBufferWriteTest();
} catch (e) {
    print(e.stack || e);
}
